home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr07 / oleo130s.zip / OLEO130S.TAR / oleo-1.3 / regions.c < prev    next >
C/C++ Source or Header  |  1993-03-29  |  21KB  |  1,050 lines

  1. /*    Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "funcdef.h"
  20. #include <stdio.h>
  21. #include "sysdef.h"
  22. #include "global.h"
  23. #include "cell.h"
  24. #include "io-generic.h"
  25. #include "io-abstract.h"
  26. #include "io-utils.h"
  27. #include "lists.h"
  28. #include "ref.h"
  29. #include "regions.h"
  30. #include "io-term.h"
  31. #include "window.h"
  32. #include "cmd.h"
  33.  
  34.  
  35. struct rng all_rng = {MIN_ROW, MIN_COL, MAX_ROW, MAX_COL};
  36.  
  37. /* Take a struct rng (R) and init its elements to R1 C1 R2 C2, making sure
  38.    they are put in in the right order.
  39.  */
  40. #ifdef __STDC__
  41. void
  42. set_rng (struct rng *r, CELLREF r1, CELLREF c1, CELLREF r2, CELLREF c2)
  43. #else
  44. void
  45. set_rng (r, r1, c1, r2, c2)
  46.      struct rng *r;
  47.      CELLREF r1;
  48.      CELLREF c1;
  49.      CELLREF r2;
  50.      CELLREF c2;
  51. #endif
  52. {
  53.   if (r1 <= r2)
  54.     {
  55.       r->lr = r1;
  56.       r->hr = r2;
  57.     }
  58.   else
  59.     {
  60.       r->lr = r2;
  61.       r->hr = r1;
  62.     }
  63.   if (c1 <= c2)
  64.     {
  65.       r->lc = c1;
  66.       r->hc = c2;
  67.     }
  68.   else
  69.     {
  70.       r->lc = c2;
  71.       r->hc = c1;
  72.     }
  73. }
  74.  
  75. /* Flush all the cells in a region */
  76. #ifdef __STDC__
  77. void
  78. delete_region (struct rng *where)
  79. #else
  80. void
  81. delete_region (where)
  82.      struct rng *where;
  83. #endif
  84. {
  85.   CELLREF rr, cc;
  86.   CELL *pp;
  87.  
  88.   modified = 1;
  89.  
  90.   find_cells_in_range (where);
  91.   while (pp = next_row_col_in_range (&rr, &cc))
  92.     {
  93.       if (!pp->cell_formula && !GET_TYP (pp))
  94.     {
  95.       pp->cell_flags = 0;
  96.       pp->cell_font = 0;
  97.       continue;
  98.     }
  99.       cur_row = rr;
  100.       cur_col = cc;
  101.       my_cell = pp;
  102.       flush_old_value ();
  103.       pp->cell_formula = 0;
  104.       pp->cell_flags = 0;
  105.       pp->cell_font = 0;
  106.       push_refs (pp->cell_refs_from);
  107.       io_pr_cell (rr, cc, pp);
  108.     }
  109.   my_cell = 0;
  110. }
  111.  
  112. /* Turn on/off the locked bits in a region */
  113. #ifdef __STDC__
  114. void
  115. lock_region (struct rng *where, int locked)
  116. #else
  117. void
  118. lock_region (where, locked)
  119.      struct rng *where;
  120.      int locked;
  121. #endif
  122. {
  123.   CELL *cp;
  124.  
  125.   modified = 1;
  126.   make_cells_in_range (where);
  127.   while (cp = next_cell_in_range ())
  128.     SET_LCK (cp, locked);
  129. }
  130.  
  131. #ifdef __STDC__
  132. void
  133. format_region (struct rng *where, int fmt, int just)
  134. #else
  135. void
  136. format_region (where, fmt, just)
  137.      struct rng *where;
  138.      int fmt;
  139.      int just;
  140. #endif
  141. {
  142.   CELL *cp;
  143.   CELLREF rr, cc;
  144.  
  145.   modified = 1;
  146.   make_cells_in_range (where);
  147.   while (cp = next_row_col_in_range (&rr, &cc))
  148.     {
  149.       if (fmt != -1)
  150.     SET_FMT (cp, fmt);
  151.       if (just != -1)
  152.     SET_JST (cp, just);
  153.       io_pr_cell (rr, cc, cp);
  154.     }
  155. }
  156.  
  157. unsigned int print_width;
  158.  
  159. #ifdef __STDC__
  160. void
  161. print_region (FILE *fp, struct rng *print)
  162. #else
  163. void
  164. print_region (fp, print)
  165.      FILE *fp;
  166.      struct rng *print;
  167. #endif
  168. {
  169.   CELLREF rr, cc;
  170.   CELL *cp;
  171.   char *ptr;
  172.   int w;
  173.   int j;
  174.   int lenstr;
  175.   int spaces;
  176.   CELLREF c_lo, c_hi;
  177.  
  178.   for (c_lo = print->lc, c_hi = 0; c_hi != print->hc; c_lo = c_hi + 1)
  179.     {
  180.       w = 0;
  181.       for (w = get_width (cc = c_lo); w <= print_width && cc <= print->hc; w += get_width (++cc))
  182.     ;
  183.       if (cc != c_lo)
  184.     --cc;
  185.       c_hi = cc;
  186.  
  187.       for (rr = print->lr; rr <= print->hr; rr++)
  188.     {
  189.       spaces = 0;
  190.       for (cc = c_lo; cc <= c_hi; cc++)
  191.         {
  192.           w = get_width (cc);
  193.           if (!w)
  194.         continue;
  195.           cp = find_cell (rr, cc);
  196.           if (!cp || !GET_TYP (cp))
  197.         {
  198.           spaces += w;
  199.           continue;
  200.         }
  201.           ptr = print_cell (cp);
  202.           lenstr = strlen (ptr);
  203.           if (lenstr == 0)
  204.         {
  205.           spaces += w;
  206.           continue;
  207.         }
  208.           if (spaces)
  209.         {
  210.           fprintf (fp, "%*s", spaces, "");
  211.           spaces = 0;
  212.         }
  213.           j = GET_JST (cp);
  214.           if (j == JST_DEF)
  215.         j = default_jst;
  216.           if (lenstr <= w - 1)
  217.         {
  218.           if (j == JST_LFT)
  219.             {
  220.               fprintf (fp, "%s", ptr);
  221.               spaces = w - lenstr;
  222.             }
  223.           else if (j == JST_RGT)
  224.             {
  225.               fprintf (fp, "%*s", w - 1, ptr);
  226.               spaces = 1;
  227.             }
  228.           else if (j == JST_CNT)
  229.             {
  230.               w = (w - 1) - lenstr;
  231.               fprintf (fp, "%*s", w / 2 + lenstr, ptr);
  232.               spaces = (w + 3) / 2;
  233.             }
  234. #ifdef TEST
  235.           else
  236.             {
  237.               panic ("What just %d", j);
  238.             }
  239. #endif
  240.         }
  241.           else
  242.         {
  243.           CELLREF ccc = cc;
  244.           CELL *ccp;
  245.           int tmp_wid;
  246.           unsigned int ww;
  247.  
  248.           for (ww = w;; tmp_wid = get_width (ccc), w += tmp_wid, spaces -= tmp_wid)
  249.             {
  250.               if (lenstr < w - 1)
  251.             break;
  252.               if (++ccc > c_hi)
  253.             break;
  254.               ccp = find_cell (rr, ccc);
  255.               if (!ccp || !GET_TYP (ccp) || GET_FMT (ccp) == FMT_HID)
  256.             continue;
  257.               if (GET_FMT (ccp) == FMT_DEF && default_fmt == FMT_HID)
  258.             continue;
  259.               break;
  260.             }
  261.           if (lenstr > w - 1)
  262.             {
  263.               if (GET_TYP (cp) == TYP_FLT)
  264.             {
  265.               ptr = adjust_prc (ptr, cp, w - 1, ww - 1, j);
  266.               lenstr = strlen (ptr);
  267.             }
  268.               else if (GET_TYP (cp) == TYP_INT)
  269.             {
  270.               ptr = numb_oflo;
  271.               lenstr = 80;
  272.             }
  273.               fprintf (fp, "%.*s", w - 1, ptr);
  274.               if (lenstr < w)
  275.             spaces += w - lenstr;
  276.               else
  277.             spaces++;
  278.             }
  279.           else
  280.             {
  281.               fprintf (fp, "%s", ptr);
  282.               spaces += w - lenstr;
  283.             }
  284.         }
  285.         }
  286.       (void) putc ('\n', fp);
  287.     }
  288.     }
  289. }
  290.  
  291.  
  292. /*
  293.    Set up regions for the move/copy functions.  This deals with default
  294.    sizing of the target region, regions that don't fit, etc.
  295.  
  296.    This returns
  297.     -1 if the regions overlap
  298.     0 if there is a *real* error
  299.     1 if the target is a multiple of the source
  300.     2 if everything is OK.
  301.  */
  302.  
  303. #ifdef __STDC__
  304. static int
  305. set_to_region (struct rng *fm, struct rng *to)
  306. #else
  307. static int
  308. set_to_region (fm, to)
  309.      struct rng *fm;
  310.      struct rng *to;
  311. #endif
  312. {
  313.   /* Delta {row,col} {from,to} */
  314.   int drf, dcf;
  315.   int drt, dct;
  316.   int ret = 2;
  317.  
  318.   drf = fm->hr - fm->lr;
  319.   drt = to->hr - to->lr;
  320.   if (drt == 0)
  321.     {
  322.       if (to->lr > MAX_ROW - drf)
  323.     {
  324.       io_error_msg ("The range won't fit this far down!");
  325.       return 0;
  326.     }
  327.       to->hr = to->lr + drf;
  328.     }
  329.   else if (drf != drt)
  330.     {
  331.       if ((drt + 1) % (drf + 1) == 0)
  332.     ret = 1;
  333.       else
  334.     {
  335.       io_error_msg ("Rows %u:%u and %u:%u don't fit", fm->lr, fm->hr, to->lr, to->hr);
  336.       return 0;
  337.     }
  338.     }
  339.   dcf = fm->hc - fm->lc;
  340.   dct = to->hc - to->lc;
  341.   if (dct == 0)
  342.     {
  343.       if (to->lc > MAX_COL - dcf)
  344.     {
  345.       io_error_msg ("The range won't fit this far over!");
  346.       return 0;
  347.     }
  348.       to->hc = to->lc + dcf;
  349.     }
  350.   else if (dcf != dct)
  351.     {
  352.       if ((dct + 1) % (dcf + 1) == 0)
  353.     ret = 1;
  354.       else
  355.     {
  356.       io_error_msg ("Cols %u:%u and %u:%u don't fit", fm->lc, fm->hc, to->lc, to->hc);
  357.       return 0;
  358.     }
  359.     }
  360.  
  361.   if (fm->lr == to->lr && fm->lc == to->lc)
  362.     {
  363.       io_error_msg ("Regions are in the same place");
  364.       return 0;
  365.     }
  366.  
  367.   if (((fm->lr <= to->lr && to->lr <= fm->hr) || (fm->lr <= to->hr && to->hr <= fm->hr))
  368.       && ((fm->lc <= to->lc && to->lc <= fm->hc) || (fm->lc <= to->hc && to->hc <= fm->hc)))
  369.     return -1;
  370.   modified = 1;
  371.   return ret;
  372. }
  373.  
  374. /* This is only complicated because it must deal with overlap, and it wants
  375.    to be smart about copying empty space. . .
  376.  */
  377. #ifdef __STDC__
  378. void
  379. move_region (struct rng *fm, struct rng *to)
  380. #else
  381. void
  382. move_region (fm, to)
  383.      struct rng *fm;
  384.      struct rng *to;
  385. #endif
  386. {
  387.   /* Delta {row,col} */
  388.   int dr, dc;
  389.   int nr, nc;
  390.   int ov, dn;
  391.   struct rng del_to_1, del_to_2;
  392.   int do_2, dirs[2];
  393.   int maxr, maxc;
  394.   CELLREF cmax, rmax;
  395.   int cdmax, rdmax;
  396.   int must_repaint = 0;        /* If this move changes cell widths/heights */
  397.  
  398.   switch (set_to_region (fm, to))
  399.     {
  400.     case 0:
  401.       return;
  402.  
  403.     case 1:
  404.       io_error_msg ("Can't move source to multiple targets");
  405.       return;
  406.  
  407.     case 2:
  408.       del_to_1 = *to;
  409.  
  410.       do_2 = 0;
  411.       dirs[0] = 1;
  412.       dirs[1] = 1;
  413.  
  414.       /* del_fm_1= *fm; */
  415.       break;
  416.  
  417.     default:
  418.       /* They overlap.  There are eight ways that
  419.            they can overlap.  */
  420.       if (to->lc == fm->lc && to->lr < fm->lr)
  421.     {
  422.       /* State 1:  'from' on bottom */
  423.       del_to_1.lr = to->lr;
  424.       del_to_1.lc = to->lc;
  425.       del_to_1.hr = fm->lr - 1;
  426.       del_to_1.hc = to->hc;
  427.  
  428.       do_2 = 0;
  429.       dirs[0] = 1;
  430.       dirs[1] = 1;
  431.  
  432.       /* del_fm_1.lr=to->hr+1;    del_fm_1.lc=fm->lc;
  433.             del_fm_1.hr=fm->hr;    del_fm_1.hc=fm->hc; */
  434.     }
  435.       else if (to->lc == fm->lc)
  436.     {
  437.       /* State 2: 'from' on top */
  438.       del_to_1.lr = fm->hr + 1;
  439.       del_to_1.lc = to->lc;
  440.       del_to_1.hr = to->hr;
  441.       del_to_1.hc = to->hc;
  442.  
  443.       do_2 = 0;
  444.       dirs[0] = -1;
  445.       dirs[1] = 1;
  446.  
  447.       /* del_fm_1.lr=fm->lr;    del_fm_1.lc=fm->lc;
  448.             del_fm_1.hr=to->lr-1;    del_fm_1.hc=fm->hc; */
  449.     }
  450.       else if (to->lr == fm->lr && to->lc < fm->lc)
  451.     {
  452.       /* State 3: 'from' on right */
  453.       del_to_1.lr = to->lr;
  454.       del_to_1.lc = to->lc;
  455.       del_to_1.hr = to->hr;
  456.       del_to_1.hc = fm->lc - 1;
  457.  
  458.       do_2 = 0;
  459.       dirs[0] = 1;
  460.       dirs[1] = 1;
  461.  
  462.       /* del_fm_1.lr=fm->lr;    del_fm_1.lc=to->hc+1;
  463.             del_fm_1.hr=fm->hr;    del_fm_1.hc=fm->hc; */
  464.     }
  465.       else if (to->lr == fm->lr)
  466.     {
  467.       /* State 4: 'from' on left */
  468.       del_to_1.lr = to->lr;
  469.       del_to_1.lc = fm->hc + 1;
  470.       del_to_1.hr = to->hr;
  471.       del_to_1.hc = to->hc;
  472.  
  473.       do_2 = 0;
  474.       dirs[0] = 1;
  475.       dirs[1] = -1;
  476.  
  477.       /* del_fm_1.lr=fm->lr;    del_fm_1.lc=fm->lc;
  478.             del_fm_1.hr=fm->hr;    del_fm_1.hc=to->lc-1; */
  479.     }
  480.       else if (fm->lr < to->lr && fm->lc < to->lc)
  481.     {
  482.       /* State 5: From on topleft */
  483.  
  484.       del_to_1.lr = to->lr;
  485.       del_to_1.lc = fm->hc + 1;
  486.       del_to_1.hr = fm->hr;
  487.       del_to_1.hc = to->hc;
  488.  
  489.       del_to_2.lr = fm->hr + 1;
  490.       del_to_2.lc = to->lc;
  491.       del_to_2.hr = to->hr;
  492.       del_to_2.hc = to->hc;
  493.  
  494.       do_2 = 1;
  495.       dirs[0] = -1;
  496.       dirs[1] = -1;
  497.  
  498.       /* del_fm_1.lr=fm->lr;    del_fm_1.lc=fm->lc;
  499.             del_fm_1.hr=to->lr-1;    del_fm_1.hc=fm->hc;
  500.  
  501.             del_fm_2.lr=to->lr;    del_fm_2.lc=fm->lc;
  502.             del_fm_2.hr=fm->hr;    del_fm_2.hc=to->lc-1; */
  503.     }
  504.       else if (fm->lr < to->lr)
  505.     {
  506.       /* State 6: 'from' on topright */
  507.       del_to_1.lr = to->lr;
  508.       del_to_1.lc = to->lc;
  509.       del_to_1.hr = fm->hr;
  510.       del_to_1.hc = fm->lc - 1;
  511.  
  512.       del_to_2.lr = fm->hr + 1;
  513.       del_to_2.lc = to->lc;
  514.       del_to_2.hr = to->hr;
  515.       del_to_2.hc = to->hc;
  516.  
  517.       do_2 = 1;
  518.       dirs[0] = -1;
  519.       dirs[1] = 1;
  520.  
  521.       /* del_fm_1.lr=fm->lr;    del_fm_1.lc=fm->lc;
  522.             del_fm_1.hr=to->lr-1;    del_fm_1.hc=fm->hc;
  523.  
  524.             del_fm_2.lr=to->lr;    del_fm_2.lc=to->hc+1;
  525.             del_fm_2.hr=fm->hr;    del_fm_2.hc=fm->hc; */
  526.     }
  527.       else if (fm->lc < to->lc)
  528.     {
  529.       /* State 7: 'from on bottomleft */
  530.       del_to_1.lr = to->lr;
  531.       del_to_1.lc = to->lc;
  532.       del_to_1.hr = fm->lr - 1;
  533.       del_to_1.hc = to->hc;
  534.  
  535.       del_to_2.lr = fm->lr;
  536.       del_to_2.lc = fm->hc;
  537.       del_to_2.hr = to->hr;
  538.       del_to_2.hc = to->hc;
  539.  
  540.       do_2 = 1;
  541.       dirs[0] = 1;
  542.       dirs[1] = -1;
  543.  
  544.       /* del_fm_1.lr=fm->lr;    del_fm_1.lc=fm->lc;
  545.             del_fm_1.hr=to->hr;    del_fm_1.hc=to->lc-1;
  546.  
  547.             del_fm_2.lr=to->hr+1;    del_fm_2.lc=fm->lc;
  548.             del_fm_2.hr=to->hr+1;    del_fm_2.hc=to->lc-1; */
  549.     }
  550.       else
  551.     {
  552.       /* State 8: 'from' on bottomright */
  553.       del_to_1.lr = to->lr;
  554.       del_to_1.lc = to->lc;
  555.       del_to_1.hr = fm->lr - 1;
  556.       del_to_1.hc = to->hc;
  557.  
  558.       del_to_2.lr = fm->lr;
  559.       del_to_2.lc = to->lc;
  560.       del_to_2.hr = to->hr;
  561.       del_to_2.hc = fm->lc - 1;
  562.  
  563.       do_2 = 1;
  564.       dirs[0] = 1;
  565.       dirs[1] = 1;
  566.  
  567.       /* del_fm_1.lr=fm->lr;    del_fm_1.lc=to->hc+1;
  568.             del_fm_1.hr=to->hr;    del_fm_1.hc=fm->hc;
  569.  
  570.             del_fm_2.lr=to->hr+1;    del_fm_2.lc=fm->lc;
  571.             del_fm_2.hr=fm->hr;    del_fm_2.hc=fm->hc; */
  572.     }
  573.     }
  574.   dn = to->hr - fm->hr;
  575.   ov = to->hc - fm->hc;
  576.  
  577.   dr = fm->hr - fm->lr;
  578.   dc = fm->hc - fm->lc;
  579.  
  580.   delete_region (&del_to_1);
  581.   if (do_2)
  582.     delete_region (&del_to_2);
  583.  
  584.   if (to->lr == MIN_ROW && to->hr == MAX_ROW)
  585.     {
  586.       shift_widths (ov, fm->lc, fm->hc);
  587.       must_repaint = 1;
  588.     }
  589.  
  590.   if (to->lc == MIN_COL && to->hc == MAX_COL)
  591.     {
  592.       shift_heights (dn, fm->lr, fm->hr);
  593.       must_repaint = 1;
  594.     }
  595.  
  596.   shift_outside (fm, dn, ov);
  597.  
  598.   rmax = highest_row ();
  599.   if (rmax < fm->lr)
  600.     rdmax = -1;
  601.   else if (rmax > fm->hr)
  602.     rdmax = dr;
  603.   else
  604.     rdmax = rmax - fm->lr;
  605.   nr = (dirs[0] > 0) ? 0 : rdmax;
  606.   maxr = (dirs[0] > 0) ? rdmax + 1 : -1;
  607.   for (; nr != maxr; nr += dirs[0])
  608.     {
  609.       cmax = max_col (fm->lr + nr);
  610.       if (cmax < fm->lc)
  611.     cdmax = -1;
  612.       else if (cmax > fm->hc)
  613.     cdmax = dc;
  614.       else
  615.     {
  616.       cdmax = cmax - fm->lc;
  617.     }
  618.       nc = (dirs[1] > 0) ? 0 : cdmax;
  619.       maxc = (dirs[1] > 0) ? cdmax + 1 : -1;
  620.       for (; nc != maxc; nc += dirs[1])
  621.     {
  622.       CELLREF rf, cf, rt, ct;
  623.       CELL *cpf;
  624.  
  625.       rf = fm->lr + nr;
  626.       cf = fm->lc + nc;
  627.       rt = to->lr + nr;
  628.       ct = to->lc + nc;
  629.  
  630.       cpf = find_cell (rf, cf);
  631.       cur_row = rt;
  632.       cur_col = ct;
  633.       my_cell = find_cell (cur_row, cur_col);
  634.       if ((!cpf
  635.            || (!cpf->cell_font && !cpf->cell_flags && !cpf->cell_formula))
  636.           && !my_cell)
  637.         continue;
  638.  
  639.       if (!cpf)
  640.         {
  641.           my_cell->cell_flags = 0;
  642.           my_cell->cell_font = 0;
  643.           my_cell->cell_refs_to = 0;
  644.           my_cell->cell_formula = 0;
  645.           my_cell->cell_cycle = 0;
  646.           my_cell = 0;
  647.           continue;
  648.         }
  649.       if (!my_cell)
  650.         {
  651.           my_cell = find_or_make_cell (cur_row, cur_col);
  652.           cpf = find_cell (rf, cf);
  653.         }
  654.       else
  655.         flush_old_value ();
  656.  
  657.       my_cell->cell_flags = cpf->cell_flags;
  658.       my_cell->cell_font = cpf->cell_font;
  659.       my_cell->cell_refs_to = cpf->cell_refs_to;
  660.       my_cell->cell_formula = cpf->cell_formula;
  661.       my_cell->cell_cycle = cpf->cell_cycle;
  662.       my_cell->c_z = cpf->c_z;
  663.  
  664.       cpf->cell_flags = 0;
  665.       cpf->cell_font = 0;
  666.       cpf->cell_refs_to = 0;
  667.       cpf->cell_formula = 0;
  668.       cpf->cell_cycle = 0;
  669.  
  670.       push_cell (cur_row, cur_col);
  671.  
  672.        if (!must_repaint)
  673.         {
  674.           if (cpf)
  675.         io_pr_cell (rf, cf, cpf);
  676.           if (my_cell)
  677.         io_pr_cell (rt, ct, my_cell);
  678.         }
  679.       my_cell = 0;
  680.     }
  681.     }
  682.   if (must_repaint)
  683.     io_repaint ();
  684.   return;
  685. }
  686.  
  687. #ifdef __STDC__
  688. void
  689. copy_region (struct rng *fm, struct rng *to)
  690. #else
  691. void
  692. copy_region (fm, to)
  693.      struct rng *fm;
  694.      struct rng *to;
  695. #endif
  696. {
  697.   CELLREF rf, rt, cf, ct;
  698.  
  699.   if (set_to_region (fm, to) < 1)
  700.     return;
  701.  
  702.   for (rf = fm->lr, rt = to->lr; (rt > 0) && (rt <= to->hr); rt++, rf++)
  703.     {
  704.       for (cf = fm->lc, ct = to->lc; (ct > 0) && (ct <= to->hc); ct++, cf++)
  705.     {
  706.       copy_cell (rf, cf, rt, ct);
  707.  
  708.       if (cf == fm->hc)
  709.         cf = fm->lc - 1;
  710.     }
  711.       if (rf == fm->hr)
  712.     rf = fm->lr - 1;
  713.     }
  714. }
  715.  
  716. #ifdef __STDC__
  717. void
  718. copy_values_region (struct rng *fm, struct rng *to)
  719. #else
  720. void
  721. copy_values_region (fm, to)
  722.      struct rng *fm;
  723.      struct rng *to;
  724. #endif
  725. {
  726.   CELLREF rf, rt, cf, ct;
  727.   union vals dummy;
  728.   CELL *cpf;
  729.  
  730.   if (set_to_region (fm, to) < 1)
  731.     return;
  732.  
  733.   for (rf = fm->lr, rt = to->lr; rt <= to->hr; rt++, rf++)
  734.     {
  735.       for (cf = fm->lc, ct = to->lc; ct <= to->hc; ct++, cf++)
  736.     {
  737.       cpf = find_cell (rf, cf);
  738.       set_new_value (rt, ct, cpf ? GET_TYP (cpf) : 0, cpf ? &(cpf->c_z) : &dummy);
  739.  
  740.       if (cf == fm->hc)
  741.         cf = fm->lc - 1;
  742.     }
  743.       if (rf == fm->hr)
  744.     rf = fm->lr - 1;
  745.     }
  746. }
  747.  
  748. struct rng sort_rng;
  749. struct rng sort_ele;
  750. struct cmp *sort_keys;
  751. int sort_keys_alloc;
  752. int sort_keys_num = 0;
  753.  
  754. static int srdiff, erdiff, scdiff, ecdiff;
  755.  
  756. #ifdef TEST
  757. extern int debug;
  758. #endif
  759.  
  760. #ifdef __STDC__
  761. void
  762. sort_region (void)
  763. #else
  764. void
  765. sort_region ()
  766. #endif
  767. {
  768.   srdiff = 1 + sort_rng.hr - sort_rng.lr;
  769.   erdiff = 1 + sort_ele.hr - sort_ele.lr;
  770.  
  771.   scdiff = 1 + sort_rng.hc - sort_rng.lc;
  772.   ecdiff = 1 + sort_ele.hc - sort_ele.lc;
  773.  
  774.   if (srdiff != erdiff && srdiff % erdiff != 0)
  775.     {
  776.       io_error_msg ("Rows %u:%u and %u:%u don't fit", sort_rng.lr, sort_rng.hr, sort_ele.lr, sort_ele.hr);
  777.       return;
  778.     }
  779.   if (scdiff != ecdiff && scdiff % ecdiff != 0)
  780.     {
  781.       io_error_msg ("Cols %u:%u and %u:%u don't fit", sort_rng.lc, sort_rng.hc, sort_ele.lc, sort_ele.hc);
  782.       return;
  783.     }
  784.   if (scdiff != ecdiff && srdiff != erdiff)
  785.     {
  786.       io_error_msg ("Can't sort this region!");
  787.       return;
  788.     }
  789.   modified = 1;
  790.   if (scdiff != ecdiff)
  791.     {
  792.       erdiff = 0;
  793.       sort (scdiff / ecdiff, cmp_cells, swp_cells, rot_cells);
  794.     }
  795.   else
  796.     {
  797.       ecdiff = 0;
  798.       sort (srdiff / erdiff, cmp_cells, swp_cells, rot_cells);
  799.     }
  800. }
  801.  
  802. #ifdef __STDC__
  803. int
  804. cmp_cells (int n1, int n2)
  805. #else
  806. int
  807. cmp_cells (n1, n2)
  808.      int n1;
  809.      int n2;
  810. #endif
  811. {
  812.   CELL *c1, *c2;
  813.   int t1, t2;
  814.   union vals v1, v2;
  815.   CELLREF row1, row2, col1, col2;
  816.   int keyn;
  817.   int cmpval;
  818.  
  819.   if (n1 == n2)
  820.     return 0;
  821.  
  822.   for (keyn = 0; keyn < sort_keys_num; keyn++)
  823.     {
  824.       row1 = sort_rng.lr + (n1 * erdiff) + sort_keys[keyn].row;
  825.       col1 = sort_rng.lc + (n1 * ecdiff) + sort_keys[keyn].col;
  826.       row2 = sort_rng.lr + (n2 * erdiff) + sort_keys[keyn].row;
  827.       col2 = sort_rng.lc + (n2 * ecdiff) + sort_keys[keyn].col;
  828. #ifdef TEST
  829.       if (debug & 04)
  830.     io_error_msg ("Cmp %u %u  r%uc%u <-%u-> r%uc%u", n1, n2, row1, col1, sort_keys[keyn].mult, row2, col2);
  831. #endif
  832.       c1 = find_cell (row1, col1);
  833.       c2 = find_cell (row2, col2);
  834.       if (!c1 && !c2)
  835.     continue;
  836.  
  837.       if (c1)
  838.     {
  839.       t1 = GET_TYP (c1);
  840.       v1 = c1->c_z;
  841.     }
  842.       else
  843.     t1 = 0;
  844.       if (c2)
  845.     {
  846.       t2 = GET_TYP (c2);
  847.       v2 = c2->c_z;
  848.     }
  849.       else
  850.     t2 = 0;
  851.  
  852.       if (t1 == TYP_ERR || t1 == TYP_BOL)
  853.     {
  854.       t1 = TYP_STR;
  855.       v1.c_s = print_cell (c1);
  856.     }
  857.       if (t2 == TYP_ERR || t2 == TYP_BOL)
  858.     {
  859.       t2 = TYP_STR;
  860.       v2.c_s = print_cell (c2);
  861.     }
  862.       if (t1 != t2)
  863.     {
  864.       if (t1 == 0)
  865.         {
  866.           if (t2 == TYP_STR)
  867.         {
  868.           t1 = TYP_STR;
  869.           v1.c_s = "";
  870.         }
  871.           else if (t2 == TYP_INT)
  872.         {
  873.           t1 = TYP_INT;
  874.           v1.c_l = 0;
  875.         }
  876.           else
  877.         {
  878.           t1 = TYP_FLT;
  879.           v1.c_d = 0.0;
  880.         }
  881.         }
  882.       else if (t2 == 0)
  883.         {
  884.           if (t1 == TYP_STR)
  885.         {
  886.           t2 = TYP_STR;
  887.           v2.c_s = "";
  888.         }
  889.           else if (t1 == TYP_INT)
  890.         {
  891.           t2 = TYP_INT;
  892.           v2.c_l = 0;
  893.         }
  894.           else
  895.         {
  896.           t2 = TYP_FLT;
  897.           v2.c_d = 0.0;
  898.         }
  899.         }
  900.       else if (t1 == TYP_STR)
  901.         {
  902.           t2 = TYP_STR;
  903.           v2.c_s = print_cell (c2);
  904.         }
  905.       else if (t2 == TYP_STR)
  906.         {
  907.           t1 = TYP_STR;
  908.           v1.c_s = print_cell (c1);
  909.           /* If we get here, one is INT, and the other
  910.                is FLT  Make them both FLT */
  911.         }
  912.       else if (t1 == TYP_INT)
  913.         {
  914.           t1 = TYP_FLT;
  915.           v1.c_d = (double) v1.c_l;
  916.         }
  917.       else
  918.         {
  919.           t2 = TYP_FLT;
  920.           v2.c_d = (double) v2.c_l;
  921.         }
  922.     }
  923.       if (t1 == TYP_STR)
  924.     cmpval = strcmp (v1.c_s, v2.c_s);
  925.       else if (t1 == TYP_FLT)
  926.     cmpval = (v1.c_d < v2.c_d) ? -1 : ((v1.c_d > v2.c_d) ? 1 : 0);
  927.       else if (t1 == TYP_INT)
  928.     cmpval = (v1.c_l < v2.c_l) ? -1 : ((v1.c_l > v2.c_l) ? 1 : 0);
  929.       else
  930.     cmpval = 0;
  931.       if (cmpval)
  932.     return cmpval * sort_keys[keyn].mult;
  933.     }
  934.  
  935.   return 0;
  936. }
  937.  
  938. #ifdef __STDC__
  939. void
  940. swp_cells (int n1, int n2)
  941. #else
  942. void
  943. swp_cells (n1, n2)
  944.      int n1;
  945.      int n2;
  946. #endif
  947. {
  948.   int rn, cn;
  949.   CELLREF r1, r2, c1, c2;
  950.  
  951. #ifdef TEST
  952.   if (debug & 04)
  953.     io_error_msg ("Swap %u<-->%u", n1, n2);
  954. #endif
  955.   for (rn = sort_ele.lr; rn <= sort_ele.hr; rn++)
  956.     for (cn = sort_ele.lc; cn <= sort_ele.hc; cn++)
  957.       {
  958.     r1 = sort_rng.lr + (n1 * erdiff) + rn;
  959.     r2 = sort_rng.lr + (n2 * erdiff) + rn;
  960.     c1 = sort_rng.lc + (n1 * ecdiff) + cn;
  961.     c2 = sort_rng.lc + (n2 * ecdiff) + cn;
  962. #ifdef TEST
  963.     if (debug & 04)
  964.       io_error_msg ("Save  r%uc%u", r1, c1);
  965. #endif
  966.     move_cell (r1, c1, NON_ROW, NON_COL);
  967. #ifdef TEST
  968.     if (debug & 04)
  969.       io_error_msg ("Copy r%uc%u --> r%uc%u", r2, c2, r1, c1);
  970. #endif
  971.     move_cell (r2, c2, r1, c1);
  972.  
  973. #ifdef TEST
  974.     if (debug & 04)
  975.       io_error_msg ("Restore r%uc%u", r2, c2);
  976. #endif
  977.     move_cell (NON_ROW, NON_COL, r2, c2);
  978.  
  979.     /* push_cell(r1,c1);
  980.             push_cell(r2,c2); */
  981.       }
  982. }
  983.  
  984. #ifdef __STDC__
  985. void
  986. rot_cells (int n1, int n2)
  987. #else
  988. void
  989. rot_cells (n1, n2)
  990.      int n1;
  991.      int n2;
  992. #endif
  993. {
  994.   int rn, cn;
  995.   int nn;
  996.   CELLREF r1, r2, c1, c2;
  997.  
  998.   if (n1 + 1 == n2 || n2 + 1 == n1)
  999.     {
  1000.       swp_cells (n1, n2);
  1001.       return;
  1002.     }
  1003. #ifdef TEST
  1004.   if (debug & 04)
  1005.     io_error_msg ("Rot cells %u -- %u", n1, n2);
  1006. #endif
  1007.   for (rn = sort_ele.lr; rn <= sort_ele.hr; rn++)
  1008.     for (cn = sort_ele.lc; cn <= sort_ele.hc; cn++)
  1009.       {
  1010.  
  1011.     /* store a copy of cell # n2 */
  1012.     r2 = sort_rng.lr + (n2 * erdiff) + rn;
  1013.     c2 = sort_rng.lc + (n2 * ecdiff) + cn;
  1014.     move_cell (r2, c2, NON_ROW, NON_COL);
  1015.  
  1016. #ifdef TEST
  1017.     if (debug & 04)
  1018.       io_error_msg ("Save r%uc%u", r2, c2);
  1019. #endif
  1020.     /* Copy each cell from n1 to n2-1 up one */
  1021.     for (nn = n2; nn > n1; --nn)
  1022.       {
  1023.         r2 = sort_rng.lr + (nn * erdiff) + rn;
  1024.         c2 = sort_rng.lc + (nn * ecdiff) + cn;
  1025.  
  1026.         r1 = sort_rng.lr + ((nn - 1) * erdiff) + rn;
  1027.         c1 = sort_rng.lc + ((nn - 1) * ecdiff) + cn;
  1028.  
  1029.         move_cell (r1, c1, r2, c2);
  1030. #ifdef TEST
  1031.         if (debug & 04)
  1032.           io_error_msg ("Copy r%uc%u --> r%uc%u", r1, c1, r2, c2);
  1033. #endif
  1034.         /* push_cell(r2,c2); */
  1035.       }
  1036.  
  1037.     r1 = sort_rng.lr + (nn * erdiff) + rn;
  1038.     c1 = sort_rng.lc + (nn * ecdiff) + cn;
  1039. #ifdef TEST
  1040.     if (debug & 04)
  1041.       io_error_msg ("Restore r%uc%u", r1, c1);
  1042. #endif
  1043.     move_cell (NON_ROW, NON_COL, r1, c1);
  1044.  
  1045.     /* push_cell(r1,c1); */
  1046.       }
  1047. }
  1048.  
  1049. /* End of functions for sort_region() */
  1050.